﻿using System.Collections.Generic;
using System.Linq;
using Services;
using Views;
using System;

namespace Presenters
{
    /// <summary>
    /// Presenter for the Select Databases page of the Add Databases wizard
    /// </summary>
    public class SelectDatabasesPresenter : PresenterBase<ISelectDatabasesView>
    {
        /// <summary>
        /// Initialse the Select Database presenter
        /// </summary>
        /// <param name="view">An instance that impliments ISelectDatabasesView</param>
        /// <param name="existingDatabases">A list of databases that we already have loaded into the current query tab</param>
        public SelectDatabasesPresenter(ISelectDatabasesView view, List<Models.Database> existingDatabases)
            : base(view)
        {
            m_ExistingDatabases = existingDatabases;
        }

        /// <summary>
        /// Load a list of available databases and remove any databases from the existing database list from it
        /// </summary>
        /// <param name="dataBaseServer">The server to load databases from</param>
        public void LoadAvailableDatabases(Models.Server dataBaseServer)
        {
            if (dataBaseServer != null)
            {
                ServersService serverService = new ServersService(dataBaseServer.ServerID);
                string errorMsg;
                List<Models.Database> dbList = serverService.GetDatabases(dataBaseServer, out errorMsg);

                if (!string.IsNullOrEmpty(errorMsg))
                {
                    ViewManager.ViewFactory.DisplayError(errorMsg, "Error loading database list");
                    View.AvailableDatabases = new List<Models.Database>(); // Display an empty list
                }
                else
                {
                    View.AvailableDatabases = RemoveExistingDatabases(dbList);
                }
            }
        }

        /// <summary>
        /// Return a list of databases in the view that are marked as selected
        /// </summary>
        /// <returns>A list of selected databases</returns>
        public List<Models.Database> GetSelectedDatabases()
        {
            List<Models.Database> result = null;

            List<Models.Database> allDatabases = View.AvailableDatabases;

            if (allDatabases != null)
            {
                var selectedDatabases = (from db in allDatabases
                                         where db.Selected
                                         select db).ToList();

                result = selectedDatabases;
            }

            return result;
        }

        /// <summary>
        /// Subtract the existing databases from the list of available databases as we do not want the user to select
        /// a database that has already been selected in the currently active query tab
        /// </summary>
        /// <param name="availableDatabases">A list of databases from which we will subtract the list of existing databases</param>
        private List<Models.Database> RemoveExistingDatabases(List<Models.Database> availableDatabases)
        {
            List<Models.Database> result = null;

            if ((availableDatabases != null) && (m_ExistingDatabases != null))
            {
                // Use Linq to get a list of available databases that do not have any matches in the list of
                // existing databases. We only need to match on Database name and Server name
                var diff = (from aDb in availableDatabases
                            where (from eDb in m_ExistingDatabases
                                   where
                                       eDb.DatabaseName == aDb.DatabaseName &&
                                       eDb.DatabaseServer.ServerName == aDb.DatabaseServer.ServerName
                                   select aDb).Count() == 0
                            select aDb).ToList();

                result = diff;
            }else if(availableDatabases != null)
            {
                // We no existing databases to subtract so simply return the list of available databases we were supplied
                // with in the first place
                result = availableDatabases;
            }

            return result;
        }

        /// <summary>
        /// Select all of the available databases
        /// </summary>
        public void SelectAll()
        {
            foreach (Models.Database db in View.AvailableDatabases)
            {
                db.Selected = true;
            }
        }

        /// <summary>
        /// Select none of the available databases
        /// </summary>
        public void SelectNone()
        {
            foreach (Models.Database db in View.AvailableDatabases)
            {
                db.Selected = false;
            }
        }

        /// <summary>
        /// List of existing databases
        /// </summary>
        private List<Models.Database> m_ExistingDatabases;
    }
}
